﻿#include <winsock2.h>
#pragma comment(lib, "WS2_32")

#include <windows.h>

#define OutErr(a) cout << (a) << endl << "出错代码：" << WSAGetLastError() << endl << "出错文件：" << __FILE__ << endl << "出错行数：" << __LINE__ << endl 
#define OutMsg(a) cout << (a) << endl;

#pragma warning(disable: 4786)
#include <iostream>
#include <time.h>
#include <vector>
#include <list>
#include <map>
#include <string>
#include <algorithm>
#include "base64.h"
#include "sha1.h"
using namespace std;

typedef struct{
	SOCKET sockClient;
	int num;
	int dot[1000];
}sClient_info,*p_sClient_info;

typedef struct info{
	int length;
	int dots[1000];		
}dots_info;

list<sClient_info> sClient_info_list;
list<sClient_info>::iterator sClient_iterator;

int a=0;
int b=0;
//int c=0;//send一次就+1
int d=0;//注册一次点位就变为1

void update_dot(SOCKET *,int );//更新某个点位下的所有客户端

const int MAX=1000;//随机点位相关

struct handshake
{
	char *get;
	char *host;
	char *key;
	char *origin;
	char *protocol;
	char *version;
};


char* parse_msg( char *);
char* build_msg( char *message, int length);

//释放握手后不再使用的部分变量

void free_handshake(struct handshake* hs)
{
	if( hs->get != NULL )            free(hs->get);
	if( hs->host != NULL )           free(hs->host);
	if( hs->key != NULL )            free(hs->key);
	if( hs->protocol != NULL )       free(hs->protocol);
	if( hs->version != NULL )        free(hs->version);
}

char* match_string(const char* src, const char* pattern, char end)
{
	char buf[1024];
	memset(buf, 0, 1024);
	size_t src_len = strlen(src); 
	size_t ptn_len = strlen(pattern);
	unsigned short b=0, p=0, i=0; 
	char c='\0';
	for(i=0; i<src_len; i++)
	{
		c = src[i];
		if(p==ptn_len)
		{ // p==ptn_len 表示正在匹配中
			if(c=='\r' || c=='\n'  || (end !='\0' && c==end) ) 
			{
				p++; // 匹配结束
			} else
			{
				buf[b++]=c; // 匹配到的字符 
			}
		}else if(p<ptn_len)
		{    // 为达到匹配要求
			if(c==pattern[p])
			{
				p++;
			}
			else 
			{
				p=0;
			}
		}
	}
	size_t ret_len = strlen(buf);
	char *ret_p; 
	if( ret_len>0 )
	{
		ret_p = (char*)calloc(ret_len+1,sizeof(char)); // 加 1 为了存储 '\0'
		memcpy(ret_p, buf, ret_len);
	} else 
	{
		ret_p = NULL;
	}
	return ret_p;
}

void handshake_test(const char* src, struct handshake* hs)
{
	hs->get = match_string(src, "GET ", 0x20); // 提取空格之前
	hs->host = match_string(src, "Host: ", '\0');
	hs->key = match_string(src, "Sec-WebSocket-Key: ", '\0');	
	hs->protocol = match_string(src, "Sec-WebSocket-Protocol: ", '\0');
	hs->origin = match_string(src, "Origin: ",'\0');
	hs->version = match_string(src,"Sec-WebSocket-Version: ",'\0');
}

char *get_websocket_accept(char *buff)//buff为客户端发送的原始握手信息
{
	struct handshake hs = {NULL,NULL,NULL,NULL,NULL,NULL};
	handshake_test(buff,&hs);				
	string value= hs.key;
	cout << "key: "<< value <<endl;
	value+="258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
	//key convert
	SHA1 sha;
	unsigned int message_digest[5];

	sha.Reset();
	sha << value.c_str();

	sha.Result(message_digest);
	// convert sha1 hash bytes to network byte order because this sha1
	//  library works on ints rather than bytes
	for (int j = 0; j < 5; j++) {
		message_digest[j] = htonl(message_digest[j]);
	}

	value = base64_encode(
	reinterpret_cast<const unsigned char*>
	(message_digest),20
	);
	
	cout << "key after convert:" << value <<endl<<endl;
	char* res=new char[1024];
	strcpy(res,value.c_str());
	
	char* buffer=new char[1024];
	
	sprintf(buffer,"HTTP/1.1 101 Switching Protocols\r\n"
	"Upgrade: WebSocket\r\n"
	"Connection: Upgrade\r\n"
	"Sec-WebSocket-Accept: %s\r\n\r\n",res);
	return buffer;
}

//线程相关
DWORD WINAPI Dots_Change(LPVOID lpParameter);
HANDLE hMutex;

//全局点位号列表：长度为1000的数组，数组元素为指向包含40个SOCKET类型数据的数组的指针，该数组保存注册该点位的客户端列表。每一行的第一位均为INVALID_SOCKET
SOCKET all_dots[1000][30];

int main(int argc, char* argv[])
{
	WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS];
	SOCKET  sockArray[WSA_MAXIMUM_WAIT_EVENTS];
	int nEventTotal = 0;
	
	ULONG NonBlock = 1;
	SOCKET sServer;
	
	for (int j=0;j<1000;j++)
	{
		all_dots[j][0]=INVALID_SOCKET;
	}
	
	//初始化winsock
	WSADATA wsd;
	if (WSAStartup(MAKEWORD(2,2),&wsd)!=0)
	{
		cout << ("WSAStartup()") << endl << "出错代码：" << WSAGetLastError() << endl << "出错文件：" << __FILE__ << endl << "出错行数：" << __LINE__ << endl;
	}
	else
	{
		// 创建socket套接字
		
		if (SOCKET_ERROR == (sServer=socket(AF_INET, SOCK_STREAM, 0)))
		{
			printf("Init Socket Error!\n");
			return -1;
		}
		//绑定端口
		struct sockaddr_in servAddr;
		servAddr.sin_family = AF_INET;
		servAddr.sin_port = htons(8089);
		servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
		
		if(bind(sServer, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0)
		{
			cout << ("bind Failed!") << endl << "出错代码：" << WSAGetLastError() << endl << "出错文件：" << __FILE__ << endl << "出错行数：" << __LINE__ << endl;
			return -1;
		}
		
		// 设置监听队列为40
		if(listen(sServer, 40) != 0)
		{
			cout << ("listen Failed!") << endl << "出错代码：" << WSAGetLastError() << endl << "出错文件：" << __FILE__ << endl << "出错行数：" << __LINE__ << endl;
			return -1;
		}
		printf("开始监听！\n");
		
		WSAEVENT event = WSACreateEvent();
		WSAEventSelect(sServer,event, FD_ACCEPT|FD_CLOSE);
		eventArray[nEventTotal]= event;
		sockArray[nEventTotal] = sServer;
		nEventTotal++;
	}
	
	//线程相关
	HANDLE hThread;
	hThread=CreateThread(NULL,0,Dots_Change,NULL,0,NULL);
	CloseHandle(hThread);
	
	//创建互斥对象
	hMutex=CreateMutex(NULL,FALSE,NULL);
	
	while (true)
	{		
		//在所有事件对象上等待
		int nIndex = WSAWaitForMultipleEvents(nEventTotal,eventArray,false,WSA_INFINITE,false);
		nIndex = nIndex - WSA_WAIT_EVENT_0;
		for (int i=nIndex;i<nEventTotal;i++)
		{			
			nIndex = WSAWaitForMultipleEvents(1,&eventArray[i],true,1000,false);
			if ((nIndex==WSA_WAIT_FAILED)||(nIndex ==WSA_WAIT_TIMEOUT))
			{
				continue;
			}
			else
			{
				WSANETWORKEVENTS event;
				WSAEnumNetworkEvents(sockArray[i],eventArray[i],&event);
				if (event.lNetworkEvents & FD_ACCEPT)
				{//处理连接请求的通知
					
					if (event.iErrorCode[FD_ACCEPT_BIT]==0)
					{
						if (nEventTotal > WSA_MAXIMUM_WAIT_EVENTS)
						{
							cout <<"太多连接了！" << endl;
							continue;
						}
						struct sockaddr_in cliAddr;
						int cliAddrSize = sizeof(struct sockaddr_in);
						SOCKET sClient = accept(sServer,(struct sockaddr *)&cliAddr,&cliAddrSize);
						if (sClient == INVALID_SOCKET)
						{
							cout << ("accept failed!") << endl << "出错代码：" << WSAGetLastError() << endl << "出错文件：" << __FILE__ << endl << "出错行数：" << __LINE__ << endl;
							return -1;
						}
						printf("有客户端连接进来！\n");
						
						//这里可得到客户端的IP地址 cliAddr.sin_addr
						ioctlsocket(sClient, FIONBIO, &NonBlock);//非阻塞
						//添加到list中
						sClient_info sClient1;
						sClient1.sockClient=sClient;
						sClient1.num=0;
						sClient_info_list.push_back(sClient1);
						
						WSAEVENT event = WSACreateEvent();
						WSAEventSelect(sClient, event, FD_READ|FD_CLOSE|FD_WRITE);
						// 添加到表中
						eventArray[nEventTotal] = event;
						sockArray[nEventTotal] = sClient;
						nEventTotal++;
						cout << "No. of client: " << sClient_info_list.size() <<endl;
					}
				}
				else if (event.lNetworkEvents & FD_READ)
				{//处理接收消息的通知
					++a;//触发一次fd_read
					//cout<< "a "<< a<<endl;
					if(event.iErrorCode[FD_READ_BIT] == 0)
					{//需判断一下是否处理消息成功
						//.......
						//ProcessMsg(sockArray[i],cBuff);
						char szText[10240];
						char *message=NULL;
						memset(szText, 0, 10240);
						int nRecv = recv(sockArray[i], szText, 10240, 0);
						
						char* buffer=new char[10240];
						
						if (strncmp(szText,"GET ",strlen("GET "))==0)
						{
							buffer = get_websocket_accept(szText);
							send(sockArray[i],buffer,(int )strlen(buffer),0);
						}
						else if (szText[0]!=(char)0x88)
						{
							cout <<"nRecv " <<nRecv<<endl;
							message = parse_msg(szText);
							cout <<endl<<"Recv data(message): " << message <<endl;
							
							for (sClient_iterator=sClient_info_list.begin();sClient_iterator!=sClient_info_list.end();sClient_iterator++)
							{
								if((*sClient_iterator).sockClient==sockArray[i])
								{
									cout << "find the client in the list"<< endl;
									int ndots=0;//客户端注册点位数量
									int tmp_dot=0;
									for (int j=0;message[j]!='\0';j++)
									{								
										char tmp[5];
										int k=0;
										for (;message[j]!=';'&&message[j]!='\0';j++,k++)
										{
											tmp[k]=message[j];
										}
										tmp[k]='\0';
										WaitForSingleObject(hMutex,INFINITE);
										d=1;
										
										//WaitForSingleObject(hMutex,INFINITE);
										tmp_dot=(*sClient_iterator).dot[ndots]=atoi(tmp);//整型串转换成int
										for (int k=0; k<30; k++)
										{
											if (all_dots[tmp_dot-1][k]==INVALID_SOCKET)
											{
												all_dots[tmp_dot-1][k]=sockArray[i];
												all_dots[tmp_dot-1][k+1]=INVALID_SOCKET;
												//ReleaseMutex(hMutex);
												break;
											}
											//ReleaseMutex(hMutex);
										}
										ReleaseMutex(hMutex);
										(*sClient_iterator).num=++ndots;
									}
								}
							}
							//输出一遍所有有客户端注册的点位信息
							cout<<"所有有客户端注册的点位信息:"<<endl;
							for (int j=0;j<1000;j++)
							{
								if (all_dots[j][0]!=INVALID_SOCKET)
								{
									cout<<"dot "<<j+1<<": ";
									for (int k=0;k<30;k++)
									{									
										if (all_dots[j][k]==INVALID_SOCKET)
										{
											break;
										}
										else cout<<all_dots[j][k]<<" ";
									}
									cout<<endl;
								}
							}
							
						}
						else{
							closesocket(sockArray[i]);
							for (sClient_iterator=sClient_info_list.begin();sClient_iterator!=sClient_info_list.end();sClient_iterator++)
							{
								if((*sClient_iterator).sockClient==sockArray[i])
								{
									cout << "Clinet " << i << " closed."<< endl;
									Sleep(1);
									WaitForSingleObject(hMutex,INFINITE);
									for (int j=0,tmp_dot=0; j<(*sClient_iterator).num; j++)
									{
										tmp_dot=(*sClient_iterator).dot[j];
										for (int k=0; k<30; k++)
										{
											if (all_dots[tmp_dot-1][k]==sockArray[i])
											{
												for (;k<29;k++)
												{
													all_dots[tmp_dot-1][k]=all_dots[tmp_dot-1][k+1];
												}
												break;
											}
										}
									}
									ReleaseMutex(hMutex);
									sClient_info_list.erase(sClient_iterator);
									break;
								}
							}
							for (int j=i;j<nEventTotal-1;j++)
							{
								sockArray[j]=sockArray[j+1];
								eventArray[j] = eventArray[j+1];
							}
							nEventTotal--;
						}
					}
				}				
				else if (event.lNetworkEvents & FD_CLOSE)
				{//处理连接关闭的通知
					//cout << c<<endl;
					if(event.iErrorCode[FD_CLOSE_BIT] == 0)
					{
						closesocket(sockArray[i]);
						
						cout << "Find the client closing."<< endl;
						//从list中删去该客户端					
						for (sClient_iterator=sClient_info_list.begin();sClient_iterator!=sClient_info_list.end();sClient_iterator++)
						{
							if((*sClient_iterator).sockClient==sockArray[i])
							{
								cout << "Clinet " << i << " closed."<< endl;
								Sleep(1);
								WaitForSingleObject(hMutex,INFINITE);
								for (int j=0,tmp_dot=0; j<(*sClient_iterator).num; j++)
								{
									tmp_dot=(*sClient_iterator).dot[j];
									for (int k=0; k<30; k++)
									{
										if (all_dots[tmp_dot-1][k]==sockArray[i])
										{
											for (;k<29;k++)
											{
												all_dots[tmp_dot-1][k]=all_dots[tmp_dot-1][k+1];
											}
											break;
										}
									}
								}
								ReleaseMutex(hMutex);
								sClient_info_list.erase(sClient_iterator);
								break;
							}
						}
						//输出一遍所有有客户端注册的点位信息
						cout<<"所有有客户端注册的点位信息:"<<endl;
						
						for (int j=0;j<1000;j++)
						{
							if (all_dots[j][0]!=INVALID_SOCKET)
							{
								cout<<"dot "<<j+1<<" ";
								for (int k=0;k<30;k++)
								{									
									if (all_dots[j][k]==INVALID_SOCKET)
									{
										cout<<all_dots[j][k]<<" ";
										break;
									}
									else cout<<all_dots[j][k]<<" ";
								}
								cout<<endl;
							}
						}
						
						
						for (int j=i;j<nEventTotal-1;j++)
						{
							sockArray[j]=sockArray[j+1];
							eventArray[j] = eventArray[j+1];
						}
						nEventTotal--;
						
						cout<< sClient_info_list.size() <<" client in the list. " << nEventTotal <<" socket in the array." << endl;
					}
					else {//连接意外关闭				
						closesocket(sockArray[i]);
						
						cout << "Find the client closing."<< endl;
						//从list中删去该客户端					
						for (sClient_iterator=sClient_info_list.begin();sClient_iterator!=sClient_info_list.end();sClient_iterator++)
						{
							if((*sClient_iterator).sockClient==sockArray[i])
							{
								cout << "Clinet " << i << " closed."<< endl;
								Sleep(1);
								WaitForSingleObject(hMutex,INFINITE);
								for (int j=0,tmp_dot=0; j<(*sClient_iterator).num; j++)
								{
									tmp_dot=(*sClient_iterator).dot[j];
									for (int k=0; k<30; k++)
									{
										if (all_dots[tmp_dot-1][k]==sockArray[i])
										{
											for (;k<29;k++)
											{
												all_dots[tmp_dot-1][k]=all_dots[tmp_dot-1][k+1];
											}
											break;
										}
									}
								}
								ReleaseMutex(hMutex);
								sClient_info_list.erase(sClient_iterator);
								break;
							}
						}
						for (int j=i;j<nEventTotal-1;j++)
						{
							sockArray[j]=sockArray[j+1];
							eventArray[j] = eventArray[j+1];
						}
						nEventTotal--;
						
						cout<< sClient_info_list.size() <<" client in the list. "<< endl;
					}
				}
				else if (event.lNetworkEvents & FD_WRITE)
				{//处理FD_WRITE通知消息
					b++;
					cout<<"FD_WRITE触发一次 b++: "<<b<< endl;
				}
				
			}
			
		}
	}
	WSACleanup();//释放资源的操作
	return 1;
}

//线程的入口函数， 监控点位变化并发给客户端
DWORD WINAPI Dots_Change(LPVOID lpParameter)//thread data
{
	Sleep(100);
	srand((unsigned)time(NULL));
	while(true)
	{
		Sleep(1);		
		int j=rand()%MAX;
		WaitForSingleObject(hMutex,INFINITE);		
		update_dot(all_dots[j],j);
		ReleaseMutex(hMutex);
	}
	return 0;
	
}

//处理点位更新的操作
void update_dot(SOCKET *dot_sockets1,int j)
{
	SOCKET *dot_sockets=dot_sockets1;//第j+1号点下面注册的客户端们
	int dot_j=j+1;//j+1号点
	if (dot_sockets[0]!=INVALID_SOCKET)
	{
		for (int k=0;k<30;k++)
		{									
			if (dot_sockets[k]==INVALID_SOCKET)
			{
				break;
			}
			else {
				char msg1[20],msg[100]="dot ";
				char *msgg;
				sprintf(msg1,"%d",dot_j);
				
				strcat(msg1," has changed.");
				strcat(msg,msg1);
				msgg=build_msg(msg,sizeof(msg));
				send(dot_sockets[k],msgg,sizeof(msg)+2,0);
			}
		}
	}
}

//解包
char* parse_msg( char *buff)
{
	char *message=new char[2048];
	if(buff[1]&0x80)
	{
		int mlen=buff[1]&0x7F;//payload len，数据长度
		
		if (mlen<126)
		{
			cout<< endl << "mlen:"<< mlen<< endl;
			for (int i=0;i<mlen;i++)
			{
				message[i]=buff[6+i]^buff[i%4+2];//第3 4 5 6字节为掩码，第7个字节开始为数据
			}
			message[mlen]='\0';
		}
		else if(mlen==126)
		{
			mlen=(unsigned char)buff[2]*256+(unsigned char)buff[3];//实际数据长度，占2字节
			cout<< endl << "mlen:"<< mlen<< endl;
			for (int i=0;i<mlen;i++)
			{
				message[i]=buff[8+i]^buff[i%4+4];//第5 6 7 8字节为掩码，第9个字节开始为数据
			}
			message[mlen]='\0';
		}
	}
	return message;
}

//打包，无掩码
char* build_msg( char *message, int length)
{
	char *buff=new char[2048];
	buff[0]=0x81;//第一个字节
	if (length<126)
	{
		buff[1]=length;		
		for (int i=0;i<length;i++)
		{
			buff[2+i]=message[i];//第3个字节开始存数据
		}
	}
	else if (length<65535)
	{
		buff[1]=126;
		buff[2]=(length>>8)&0xFF;
		buff[3]=length&0xFF;//第3 4个字节存数据长度
		for (int i=0 ;i<length;i++)
		{
			buff[4+i]=message[i];//第5个字节开始存数据
		}
	}
	
	return buff;
}

